package processmining;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.deckfour.xes.model.XLog;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.processmining.service.IEventLogService;
import com.processmining.support.C_netFormatter.format.Formatter;
import com.processmining.support.C_netFormatter.format.TransitionSystem;
import com.processmining.support.analyseSupport.entity.SankeyActivity;
import com.processmining.support.analyseSupport.entity.SankeyDiagram;
import com.processmining.support.analyseSupport.entity.SankeyItem;
import com.processmining.support.eventLogParse.EventLogParse;
import com.processmining.support.eventLogParse.impl.EventLogParseImpl;
import com.processmining.support.mining.entity.NetElement;
import com.processmining.util.JarUtil;

import net.ProcessMining.models.heuristics.HeuristicsNet;
import net.ProcessMining.models.heuristics.impl.HNSubSet;

public class MiningTest2 {
	public static JarUtil util;
	
	public static void main(String[] args) throws Exception{
		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{
	  			  "classpath:/spring/spring-service.xml",
	  			  "classpath:/spring/spring-mybatis.xml",
	  			  "classpath:/spring/spring-hdfs.xml"});
		IEventLogService eventlogService = (IEventLogService) ac.getBean("eventLogServiceImpl");
		
		
		
		// 路径
		String path = "F:/test/genetic.jar";
		//getJarMethod(path);
		Integer eventLogId = 1;
		
		// 算法名称
		String packageName = "net.ProcessMining.mining.genetic.miner.";
		String className = "MinerWrapper";
		String methodName = "logMine";
	
		
		// 从hdfs下载事件日志
		InputStream input = eventlogService.downloadLog(1);
		
		// 事件日志转换为XLOG
		EventLogParse parser = new EventLogParseImpl();
		XLog log = parser.eventLogParse(input);
		input.close();
		
		
		
		
		// 反射调用jar包里的方法
		File file=new File(path);//jar包的路径
		URL url=file.toURI().toURL();
		
		util = new JarUtil(new URL[]{url});
		Constructor c2 = util.getConstructor(packageName+className);
		Object gmObj =  c2.newInstance();
		Method method2 = util.getMethod(gmObj.getClass(), methodName,XLog.class,HashMap.class);	
		HeuristicsNet net = (HeuristicsNet) method2.invoke(gmObj,log,new HashMap());		// 调用mine()挖掘

		String usedTime = (String) util.invokeMethodWithoutParam(gmObj, "getUsedTime");

		List<NetElement> res = transform(net,usedTime);
		
		ObjectMapper mapper = new ObjectMapper();
		System.out.println(mapper.writeValueAsString(res));
		
		
		
		Method tracesM = gmObj.getClass().getMethod("getTraces");
		List<String> traces = (List<String>) tracesM.invoke(gmObj);
		
		Method allTracesM = gmObj.getClass().getMethod("getAllTraces");
		List<String> allTraces = (List<String>) allTracesM.invoke(gmObj);
		
		Formatter formatter = new TransitionSystem(net, usedTime, traces, allTraces);

        //Formatter formatter=new ResourceRelation(net,usedTime,"org:resource",xlog,2);
		
		try{
		       PrintStream out = new PrintStream("E:\\mineTest\\TransitionSystemOut.txt");
		       System.setOut(out);
		}catch(FileNotFoundException e){
		       e.printStackTrace();
		}
		System.out.println(mapper.writeValueAsString(formatter));
		
		
	}
	
	
	
public static List<NetElement> transform(HeuristicsNet net,String time){
		
		List<NetElement> netElementList = new ArrayList<NetElement>();
		Map<Integer,String> names = new HashMap<Integer,String>();
		int size = net.size();
		for(int i=0;i<size;i++){
			names.put(i, net.getActivitiesMappingStructures().getXEventClasses().getByIndex(i).toString());
		}
		HNSubSet starts = net.getStartActivities();
		int start = starts.get(0);
		HNSubSet ends = net.getEndActivities();
		int end = ends.get(0);
		
		int startCount = 0;
		int endCount = 0;
		
		for(int i=0;i<size;i++){
			
			String name = names.get(i);
			NetElement netElement = new NetElement();
			int inputSetSize = net.getInputSet(i).size();
			int outputSetSize = net.getOutputSet(i).size();
			List<String> outputs = new ArrayList<String>();
			List<Integer> subnetlist = new ArrayList<Integer>();
			for(int j=0;j<outputSetSize;j++){
				int subSetSize = net.getOutputSet(i).get(j).size();
				subnetlist.add(subSetSize);
				for(int k=0;k<subSetSize;k++){
					outputs.add(names.get(net.getOutputSet(i).get(j).get(k)));					
				}				
			}
			
			netElement.setElement(Integer.toString(i));
			netElement.setName(name);
			netElement.setOutput(outputs);
			netElement.setSubnetNum(outputSetSize);
			netElement.setSubnetList(subnetlist);
			netElement.setTime(time);
			netElementList.add(netElement);
			
			if(starts.contains(i)){
				System.out.println("startIndex:" + i);
				System.out.println("start:" + name);
			}
			if(ends.contains(i)){
				System.out.println("end:" + name);
			}
			
			if(inputSetSize==0){
				netElement.setIsStart("true");
				startCount++;
			}
			else{
				netElement.setIsStart("false");
			}
			
			if(outputs.size()>0){
				netElement.setIsEnd("false");
			}
			else{
				netElement.setIsEnd("true");
				endCount++;
			}
			
		}
		
		if(startCount == 0){
			for(int i=0;i<starts.size();i++){
				netElementList.get(starts.get(i)).setIsStart("true");
			}
		}
		if(endCount == 0){
			for(int i=0;i<ends.size();i++){
				netElementList.get(ends.get(i)).setIsEnd("true");
			}
		}
		
		
		int currentStart = 0;
		int currentEnd = size-1;
		for(int i=0;i<size;i++){
			
			if(netElementList.get(i).getElement().equals(Integer.toString(start)))
				currentStart = i;
			if(netElementList.get(i).getElement().equals(Integer.toString(end)))
				currentEnd = i;
			
		}
		
		if(currentStart != 0)			
			Collections.swap(netElementList,0,currentStart);
		if(currentEnd != size-1)			
			Collections.swap(netElementList,size-1,currentEnd);			
		
		return netElementList;
		
	}
    
		
	
	
	/**
	 * 将因果矩阵转化成nodes，links形式的json数据
	 * @param SankeyDiagram
	 * @return
	 * @throws JSONException 
	 */
	public static String transform(SankeyDiagram diagram) throws JSONException{
		JSONObject json=new JSONObject();  
	    JSONArray links = new JSONArray(); 
	    JSONArray nodes = new JSONArray(); 
		Set repeatSet=new HashSet<String>();
		for(SankeyActivity activity:diagram.getSankeyActivities()){
			String source=activity.getName();
			JSONObject node = new JSONObject(); 
			node.put("name", source);
			nodes.put(node);
			Map<Integer, List<SankeyItem>> map=activity.getOutputs();
			if(map.size()>0){
				Set<Integer> keySet=activity.getOutputs().keySet();  
			       Iterator<Integer> iterator=keySet.iterator();  
			       while(iterator.hasNext()){  
			           int key=iterator.next();  
			           List<SankeyItem> val=map.get(key); 
			           for(SankeyItem item:val){
			        	   String target=item.getName();
			        	   if(source.equalsIgnoreCase(target))//去掉自循环的路径
			        		   continue;
			        	   if(repeatSet.contains(source+target)||repeatSet.contains(target+source)){
			        		 //去掉短循环的路径
			        		   System.out.println("repeat:"+source+target);
			        		   continue;
			        	   }
			        		   JSONObject link = new JSONObject(); 
				        	   link.put("source", source);
				        	   link.put("target", item.getName());
				        	   link.put("value", item.getCounts()+"");
				        	   links.put(link);
				        	   repeatSet.add(source+target);
			           }
			       }  
			}
		}
		
		json.put("links", links);
		json.put("nodes", nodes);
		return json.toString();
	}
	

	
	
}
